package SceneTrigger

import (
	"GameLogic/Scene"
	"fmt"
	"misc/Clojure"
	. "misc/Clojure/parse"
)

const (
	TriggerCljPath = "../../Public/Configs/GameCore/GameTrigger.clj"
)

func InitClojureScript() {
	defineTriggerSymbol()
	buildClojureASTTree()
	initblockActionFuncs()
}

func buildClojureASTTree() {
	Clojure.LoadAstTree(TriggerCljPath, "Trigger")
}
func defineTriggerSymbol() {
	Clojure.MainContext.Define("def-trigger", Clojure.NativeFunction{MyFunction: _def_Trigger})
	Clojure.MainContext.Define("def-event", Clojure.NativeFunction{MyFunction: _def_Event})
	Clojure.MainContext.Define("def-actions", Clojure.NativeFunction{MyFunction: _def_actions})
	Clojure.MainContext.Define("action", Clojure.NativeFunction{MyFunction: _action})
	defineClojureActions()
}

/*
(def-trigger "触发器介绍"
  [(def-event "GameLoadEvent")]
  (true)
  (def-actions
    (action create-starting-units)
  )
)
*/
func _def_Trigger(args []Node, context *Clojure.Context) Node {
	newTrigger := &Trigger{}
	newTrigger.Context = Clojure.NewContext(context)
	newTrigger.Events = make([]IEvent, 0)
	scene := context.LookUp("CurScene").(*ObjectNode).Val.(*Scene.Scene)
	newTrigger.Scene = scene
	//Desc
	if strNode, ok := args[0].(*StringNode); ok {
		newTrigger.Desc = strNode.Val
	}
	//events
	vNode := args[1].(*VectorNode)
	for i := 0; i < len(vNode.Children()); i++ {
		eventNode := Clojure.Evaluate(vNode.Children()[i], context)
		newTrigger.AddEvent(eventNode.(*ObjectNode).Val.(IEvent))
	}
	actionArg := 2
	//Condition
	if len(args) == 4 {
		actionArg++
		newTrigger.ConditionNode = args[2]
	}
	//Actions
	newTrigger.Actions = Clojure.Evaluate(args[actionArg], context).(ObjectNode).Val.([]ITriggerAction)
	for i := 0; i < len(newTrigger.Actions); i++ {
		newTrigger.Actions[i].GetActionInfo().CurTrigger = newTrigger
	}
	//AddToGameTrigger
	scene.Trigger.(*SceneTrigger).AddTrigger(newTrigger)
	return nil
}

func _def_Event(args []Node, context *Clojure.Context) Node {
	newEvent := &ObjectNode{}
	eventName := ""
	if strNode, ok := args[0].(*StringNode); ok {
		eventName = strNode.Val
	} else {
		fmt.Println("def-event error")
	}
	newEvent.Val = CreateEvent(eventName, args)
	return newEvent
}

func _def_actions(args []Node, context *Clojure.Context) Node {
	actionCount := len(args)
	actions := make([]ITriggerAction, actionCount)
	for i := 0; i < actionCount; i++ {
		lstNode := args[i].(*ListNode)
		if lstNode != nil {
			actionNode := Clojure.Evaluate(lstNode, context)
			actions[i] = actionNode.(*ObjectNode).Val.(ITriggerAction)
		}
	}
	retNode := ObjectNode{Val: actions}
	return retNode
}

func _action(args []Node, context *Clojure.Context) Node {
	lstNode := new(ListNode)
	lstNode.Nodes = args
	actionName := args[0].(*SymbolNode).Val
	//如果从脚本作用域中找到了这个动作那么他就是一个非阻塞动作
	if funcNode := context.LookUp(actionName); funcNode != nil {
		NoneBlockAction := NewNonBlockAction(lstNode)
		retNode := &ObjectNode{Val: NoneBlockAction}
		return retNode
	} else {
		//如果没找到他就是一个阻塞动作
		fn := GetBlockActionNewFunc(actionName)
		blockAction := fn(args)
		blockAction.GetActionInfo().ActionNode = lstNode
		retNode := &ObjectNode{Val: blockAction}
		return retNode
	}
	return lstNode
}
